home *** CD-ROM | disk | FTP | other *** search
/ Practical Algorithms for Image Analysis / Practical Algorithms for Image Analysis.iso / CH_3.9 / THRESHK / THRESHK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1999-09-11  |  5.8 KB  |  210 lines

  1. /* 
  2.  * threshk.c
  3.  * 
  4.  * Practical Algorithms for Image Analysis
  5.  * 
  6.  * Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
  7.  */
  8.  
  9. /* THRESHK:     program performs binarization by Kittler's method
  10.  *                    usage: threshk in.tif out.tif [-i] [-L]
  11.  *
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <images.h>
  18. #include <tiffimage.h>
  19. #include <math.h>
  20. extern void print_sos_lic ();
  21.  
  22. #define MINCONTRAST_DFLT 10     /* default minimum contrast % of max */
  23. #define MAX_DEV_LEVEL_DFLT 15   /* max. dev. from level % of max */
  24. #define MINRUN_DFLT 1           /* min. run length for it to count */
  25. #define TRANSWID_DFLT 5         /* max. transition width [pixels] */
  26. #define THICK_PARAM_DFLT 80     /* thickness param */
  27.      /* % of threshold range from top */
  28.  
  29. #define MULTIOUTFLAG_DFLT 0     /* =1 to output multilevel img; or 0 */
  30. #define HISTFLAG_DFLT 1         /* =1 to display hist on imgs; or 0 */
  31. #define PROF_FRACT_THRESH 0.84  /* threshold on sliding profile */
  32.  
  33. #define BIG 100000000.0
  34. #define NHIST 256               /* no. bins in histogram */
  35. #define NTHRESH 20              /* max no. of threshold ranges */
  36.  
  37. long input (int, char **, short *);
  38. long usage (short);
  39.  
  40. main (
  41.        int argc,
  42.        char *argv[])
  43. {
  44.   Image *imgI, *imgO;           /* I/O image structures */
  45.   unsigned char **imgIn, **imgOut;  /* input and output images */
  46.   long width, height;           /* image size */
  47.   long iHist[NHIST];            /* hist. of intensities */
  48.   long x, y;                    /* image coordinates */
  49.   long i, j;
  50.  
  51.   double m0Low, m0High, m1Low, m1High, varLow, varHigh;
  52.   double term1, term2;
  53.   double prob[NHIST];
  54.   double stdDevLow, stdDevHigh;
  55.   double discr, discrMin, discrMax, discrM1;
  56.   long thresh;
  57.   short invertFlag;             /* if =0, dark -> ON; if =1, dark -> OFF */
  58.   long nHistM1;
  59.   long n;
  60.   double sqrt (), log ();
  61.  
  62.   if (input (argc, argv, &invertFlag) < 0)
  63.     return (-1);
  64.  
  65. /* allocate input and output image memory */
  66.   imgI = ImageIn (argv[1]);
  67.   imgIn = ImageGetPtr (imgI);
  68.   height = ImageGetHeight (imgI);
  69.   width = ImageGetWidth (imgI);
  70.   imgO = ImageAlloc (height, width, 8);
  71.   imgOut = ImageGetPtr (imgO);
  72.  
  73. /* compile histogram */
  74.   for (i = 0; i < NHIST; i++)
  75.     iHist[i] = 0;
  76.   for (y = 0, n = 0; y < height; y++) {
  77.     for (x = 0; x < width; x++) {
  78.       iHist[imgIn[y][x]]++;
  79.       n++;
  80.     }
  81.   }
  82.  
  83. /* compute probabilities */
  84.   for (i = 0; i < NHIST; i++)
  85.     prob[i] = (double) iHist[i] / (double) n;
  86.  
  87. /* find best threshold by computing discriminant function */
  88.   nHistM1 = NHIST - 1;
  89.   discr = discrM1 = discrMax = discrMin = 0.0;
  90.   for (i = 1, thresh = 0; i < nHistM1; i++) {
  91.     m0Low = m0High = m1Low = m1High = varLow = varHigh = 0.0;
  92.     for (j = 0; j <= i; j++) {
  93.       m0Low += prob[j];
  94.       m1Low += j * prob[j];
  95.     }
  96.     m1Low = (m0Low != 0.0) ? m1Low / m0Low : i;
  97.     for (j = i + 1; j < NHIST; j++) {
  98.       m0High += prob[j];
  99.       m1High += j * prob[j];
  100.     }
  101.     m1High = (m0High != 0.0) ? m1High / m0High : i;
  102.     for (j = 0; j <= i; j++)
  103.       varLow += (j - m1Low) * (j - m1Low) * prob[j];
  104.     stdDevLow = sqrt (varLow);
  105.     for (j = i + 1; j < NHIST; j++)
  106.       varHigh += (j - m1High) * (j - m1High) * prob[j];
  107.     stdDevHigh = sqrt (varHigh);
  108.  
  109.     if (stdDevLow == 0.0)
  110.       stdDevLow = m0Low;
  111.     if (stdDevHigh == 0.0)
  112.       stdDevHigh = m0High;
  113.     term1 = (m0Low != 0.0) ? m0Low * log (stdDevLow / m0Low) : 0.0;
  114.     term2 = (m0High != 0.0) ? m0High * log (stdDevHigh / m0High) : 0.0;
  115.     discr = term1 + term2;
  116.     if (discr < discrM1)
  117.       discrMin = discr;
  118.     if (discrMin != 0.0 && discr >= discrM1)
  119.       break;
  120.     discrM1 = discr;
  121.   }
  122.  
  123.   thresh = i;
  124.   printf ("Calculated threshold value (by Kittler/Illingworth method) = %d.\n", thresh);
  125.  
  126. /* output thresholded image */
  127.   if (invertFlag == 0) {
  128.     for (y = 0, n = 0; y < height; y++)
  129.       for (x = 0; x < width; x++)
  130.         imgOut[y][x] = (imgIn[y][x] > thresh) ? 255 : 0;
  131.   }
  132.   else {
  133.     for (y = 0, n = 0; y < height; y++)
  134.       for (x = 0; x < width; x++)
  135.         imgOut[y][x] = (imgIn[y][x] < thresh) ? 255 : 0;
  136.   }
  137.  
  138.   ImageOut (argv[2], imgO);
  139.   return (0);
  140. }
  141.  
  142.  
  143. /* USAGE:       function gives instructions on usage of program
  144.  *                    usage: usage (flag)
  145.  *              When flag is 1, the long message is given, 0 gives short.
  146.  */
  147.  
  148. long
  149. usage (flag)
  150.      short flag;                /* flag =1 for long message; =0 for short message */
  151. {
  152.  
  153. /* print short usage message or long */
  154.   printf ("USAGE: threshk inimg outimg [-i] [-L]\n");
  155.   if (flag == 0)
  156.     return (-1);
  157.  
  158.   printf ("\nthreshk performs binarization with respect to\n");
  159.   printf ("automatically determined intensity threshold;\n");
  160.   printf ("the input gray-level image is converted to a binary image;\n");
  161.   printf ("threshold determination is made by Kittler's\n");
  162.   printf ("minimum error method.\n\n");
  163.   printf ("ARGUMENTS:\n");
  164.   printf ("    inimg: input image filename (TIF)\n");
  165.   printf ("   outimg: output image filename (TIF)\n\n");
  166.   printf ("OPTIONS:\n");
  167.   printf ("      -i: INVERT: intensities ABOVE (lighter) threshold set to 0\n");
  168.   printf ("          and those BELOW (darker) threshold set to 255\n");
  169.   printf ("      -L: print Software License for this module\n");
  170.  
  171.   return (-1);
  172. }
  173.  
  174.  
  175. /* INPUT:       function reads input parameters
  176.  *                  usage: input (argc, argv)
  177.  */
  178.  
  179. #define USAGE_EXIT(VALUE) {usage (VALUE); return (-1);}
  180.  
  181. long
  182. input (argc, argv, invertFlag)
  183.      int argc;
  184.      char *argv[];
  185.      short *invertFlag;         /* if =0, dark -> ON; if =1, dark -> OFF */
  186. {
  187.   long n;
  188.  
  189.   *invertFlag = 0;
  190.  
  191.   if (argc == 1)
  192.     USAGE_EXIT (1);
  193.   if (argc == 2)
  194.     USAGE_EXIT (0);
  195.  
  196.   for (n = 3; n < argc; n++) {
  197.     if (strcmp (argv[n], "-i") == 0) {
  198.       *invertFlag = 1;
  199.     }
  200.     else if (strcmp (argv[n], "-L") == 0) {
  201.       print_sos_lic ();
  202.       exit (0);
  203.     }
  204.     else
  205.       USAGE_EXIT (0);
  206.   }
  207.  
  208.   return (0);
  209. }
  210.